/**
 * useEffect
 *
 *    语法：
 *      useEffect(setup, dependencies?)
 *        setup - 回调函数
 *        dependencies - 依赖项数组
 *
 *    setup:
 *      一个函数，该函数在会组件初始化挂载完成之后触发一次，后续当 dependencies 中描述的依赖项发生更新时会再次触发
 *
 *      它可以返回一个函数，该函数就是一个清理函数 clean
 *    clean:
 *      一个清理回调函数，它的触发时机是
 *          1. 当组件重新Render引起当前 setup 再次触发之前先触发 clean
 *          2. 当组件卸载之前按触发 clean
 *    dependencies:
 *      1. 未传递，就相当于全是依赖项，只要组件重新Render就会引起 setup 再次执行
 *      2. 一个数组
 *        1.1 空数组，没有依赖项，只会在组件挂载完成之后触发一次 setup
 *        1.2 非空数组，数组中每一项就是一个依赖项
 *
 *    PS:
 *      1. 使用 useEffect 模拟挂载完成这个生命周期
 *          useEffect(() => {}, [])
 *
 *      2. 使用 useEffect 模拟更新完成这个生命周期
 *          useEffect(() => {}, [state, prop])
 *          自定义hook
 *
 *      3. 使用 useEffect 模拟卸载之前这个生命周期
 *          effect 回调函数中，返回一个函数，该返回的函数就可以看成卸载之前
 */

import { FC, useEffect, useRef, useState } from "react";

/**
 * 自定义hook
 *    useWatch
 */
function useWatch(source, callback) {
  // 1. 定义一个 isMounted state 数据，用于表示组件是否挂载完成
  const [isMounted, setIsMounted] = useState(false);

  // 2. useEffect
  useEffect(() => {
    setIsMounted(true);
    if (isMounted) {
      callback();
    }
  }, [source]);
}

const Hello: FC<{ name: string }> = ({ name }) => {
  // const [isMounted, setIsMounted] = useState(false);

  // useEffect(() => {
  //   // 模拟组件挂载完成
  // }, []);

  // useEffect(() => {
  //   setIsMounted(true);
  //   if (isMounted) {
  //     console.log("Hello Effect");
  //   }
  // }, [name]);

  // useWatch(name, () => {
  //   console.log("Hello Name 更新了");
  // });

  useEffect(() => {
    console.log("!!! Hello Name");

    const timer = setInterval(() => {
      console.log("!!! 1");
    }, 1000);

    return () => {
      clearInterval(timer);
    };
  }, [name]);

  return <p>Hello,{name}</p>;
};

export default function App() {
  const h1Ref = useRef<HTMLHeadingElement>(null);

  const [count, setCount] = useState(1);
  const [msg, setMsg] = useState("a");
  const [show, setShow] = useState(true);

  useEffect(() => {
    console.log("effect", h1Ref.current?.innerHTML);
  }, [count]);

  useEffect(() => {
    console.log("effect msg");
  }, [msg]);

  useEffect(() => {
    console.log("=== App msg");

    // 返回一个函数
    return () => {
      console.log("=== App msg clean");
    };
  }, [msg]);

  return (
    <div>
      <h1 ref={h1Ref}>App</h1>

      {show && <Hello name={msg} />}

      <button onClick={() => setCount(count + 1)}>{count}</button>
      <button onClick={() => setMsg(msg + "a")}>{msg}</button>
      <button onClick={() => setShow(!show)}>{`` + show}</button>
    </div>
  );
}
